package com.yuwen.yuwenRPC.protocol;

/**
 * @ClassNameProtocolMessageDecoder
 * @Description TODO
 * @Author钰玟
 * @Date2025/4/2 下午8:39
 * @Version 1.0
 **/

import com.yuwen.yuwenRPC.model.RpcRequest;
import com.yuwen.yuwenRPC.model.RpcResponse;
import com.yuwen.yuwenRPC.serializer.Serializer;
import com.yuwen.yuwenRPC.serializer.SerializerFactory;
import io.vertx.core.buffer.Buffer;

import java.io.IOException;

/**
 * 消息解码器
 */
public class ProtocolMessageDecoder {

    public static ProtocolMessage<?> decode(Buffer buffer) throws IOException {

        ProtocolMessage.Header header = new ProtocolMessage.Header();
        byte magic = buffer.getByte(0);

//        System.err.println(magic);


        if (magic !=ProtocolConstant.PROTOCOL_MAGIC){
            throw new RuntimeException("消息 magic 非法");
        }

        header.setMagic(magic);
        header.setVersion(buffer.getByte(1));
        header.setSerializer(buffer.getByte(2));
        header.setType(buffer.getByte(3));
        header.setStatus(buffer.getByte(4));
        header.setRequestId(buffer.getLong(5));
        header.setBodyLength(buffer.getInt(13));

        //解决粘包问题只读取 指定长度的数据
        byte[] body = buffer.getBytes(17,17+header.getBodyLength());

        //解析消息体
        ProtocolMessageSerializerEnum protocolMessageSerializerEnum = ProtocolMessageSerializerEnum.getByKey(header.getSerializer());
        if (protocolMessageSerializerEnum == null){
            throw new RuntimeException("序列化的消息不存在!");
        }
        Serializer serializer = SerializerFactory.getSerializer(protocolMessageSerializerEnum.getValue());
        ProtocolMessageTypeEnum messageTypeEnum = ProtocolMessageTypeEnum.getEnumByKeY(header.getType());
        if (messageTypeEnum == null){
            throw  new RuntimeException("序列化的消息类型不存在!");
        }
        switch (messageTypeEnum){
            case REQUEST :
                RpcRequest rpcRequest = serializer.deserialize(body, RpcRequest.class);
                return new ProtocolMessage<>(header,rpcRequest);
            case RESPONSE :
                RpcResponse rpcResponse = serializer.deserialize(body, RpcResponse.class);
                return new ProtocolMessage<>(header,rpcResponse);
            case HEART_BEAT:
            case OTHER:
            default:
                throw  new RuntimeException("暂不支持该消息类型!!!");
        }

    }
}
